package hardware;

import java.util.LinkedList;
import java.util.List;

public class Processor {
	static int time = 0;
	static LinkedList<ROBEntry> rob = new LinkedList<ROBEntry>();
	static List<ReservationStation> reservationStations = new LinkedList<ReservationStation>();
	static List<FunctionalUnit> functionalUnits = new LinkedList<FunctionalUnit>();
	static long currentTime = 1;
	static int robSize = 20;
	static int m;
	static Register reg0 = new Register("R0", 0);
	static Register reg1 = new Register("R1", 4);
	static Register reg2 = new Register("R2", 0);
	static Register reg3 = new Register("R3", 3);
	static Register reg4 = new Register("R4", 0);
	static Register reg5 = new Register("R5", 1020);
	static Register reg6 = new Register("R6", 0);
	static Register reg7 = new Register("R7", 0);
	static RegisterMap registerMap = new RegisterMap();
	static Memory mem;
	static L1Cache nc;
	static L2Cache nc2;
	static L3Cache nc3;
	static Cache c;

	final static String UNDEFINED_REGISTER = "Undefined register";

	static int instructionBufferSize = 20;
	static LinkedList<Instruction> instructionBuffer = new LinkedList<Instruction>();

	static LinkedList<Instruction> list = new LinkedList<Instruction>();

	/**
	 * Get rob entry with a certain id.
	 * 
	 * @param Id
	 *            id that i want to get the robEntry with it.
	 * @return rob entry.
	 */
	public static ROBEntry getROBEntry(int Id) {
		int i = 0;
		for (; i < rob.size(); i++) {
			if (rob.get(i).getID() == Id && !rob.get(i).isFlag()) {
				return rob.get(i);
			}
		}
		return null;
	}

	/**
	 * Gets the reservation station with a certain instruction.
	 * 
	 * @param instruction
	 *            instruction that i am searching for in the reservation
	 *            station.
	 * @return the reservation station i want.
	 */
	public static ReservationStation getReservationStation(
			Instruction instruction) {
		for (int i = 0; i < reservationStations.size(); i++) {
			if (reservationStations.get(i).getIns().equals(instruction)) {
				return reservationStations.get(i);
			}
		}
		return null;
	}

	/**
	 * checks if instruction is in a reservation station.
	 * 
	 * @param ins
	 *            instruction i am searching for.
	 * @return the reservation station that have the instruction.
	 */
	public static ReservationStation checkReservationStation(Instruction ins) {
		for (int i = 0; i < reservationStations.size(); i++) {
			if (ins.equals(reservationStations.get(i).getIns())) {
				return reservationStations.get(i);
			}
		}
		return null;
	}

	/**
	 * reserves certain functional unit that have the same type as the
	 * instruction.
	 * 
	 * @param ins
	 *            instruction that i want to reserve functional unit for it.
	 * @return true if it's successfully reserved functional unit.
	 */
	public static boolean reserveFunctionalUnit(Instruction ins) {
		String type;
		if (ins.getType().equals(Instruction.ADD)
				|| ins.getType().equals(Instruction.ADDI)
				|| ins.getType().equals(Instruction.NAND)) {
			type = Instruction.ADD;
		} else {
			type = ins.getType();
		}
		if (!ins.getType().equals(Instruction.BRANCH_IF_EQUAL)
				&& !ins.getType().equals(Instruction.LOAD_WORD)
				&& !ins.getType().equals(Instruction.STORE_WORD)
				&& !ins.getType().equals(Instruction.RETURN)
				&& !ins.getType().equals(Instruction.JUMP)
				&& !ins.getType().equals(Instruction.JUMP_AND_LINK)) {
			for (int j = 0; j < functionalUnits.size(); j++) {
				if (!functionalUnits.get(j).reserved
						&& functionalUnits.get(j).type.equals(type)) {
					// System.out.println("Type: " + type);
					functionalUnits.get(j).reserved = true;
					functionalUnits.get(j).id = ins.getID();
					return true;
				}
			}
		} else {
			return true;
		}
		return false;
	}

	/**
	 * reserves certain reservation station that have the same type as the
	 * instruction.
	 * 
	 * @param instruction
	 *            instruction that i want to reserve reservation station for it.
	 * @return true if it's successfully reserved reservation station.
	 */
	public static boolean reserveInReservationStation(Instruction instruction) {
		for (int i = 0; i < reservationStations.size(); i++) {
			if (!reservationStations.get(i).isReserve()) {
				reservationStations.get(i).setReserve(true);
				return true;
			}
		}
		return false;
	}

	/**
	 * checks if rob is full.
	 * 
	 * @return true if the rob is full.
	 */
	public static boolean ROBIsFull() {
		return rob.size() >= robSize;
	}

	public static void program2() throws Exception {
		
		m = 2;
		reg0.setValue(5);
		reg1.setValue(0);
		reg2.setValue(4);
		reg3.setValue(2);
		reg4.setValue(7);
		reg5.setValue(2);
		reg6.setValue(10);
		reg7.setValue(1);
		
		Memory.programSize = 10;
		mem = new Memory(1024, 100);
		Memory.store(0, 4);
		Memory.store(1, 6);
		Memory.store(2, 8);
		Memory.store(3, 9);
		Memory.store(4, 110);
		Memory.store(5, 3);
		Memory.store(6, 7);
		Memory.store(7, 6);
		Memory.store(32, 100);
		Memory.store(33, 8);
		Memory.store(34, 2);
		Memory.store(34, 9);

		reservationStations.add(new ReservationStation());
		reservationStations.add(new ReservationStation());
		reservationStations.add(new ReservationStation());
		reservationStations.add(new ReservationStation());
		reservationStations.add(new ReservationStation());
		reservationStations.add(new ReservationStation());

		functionalUnits.add(new FunctionalUnit(Instruction.ADD));
		functionalUnits.add(new FunctionalUnit(Instruction.ADD));
		functionalUnits.add(new FunctionalUnit(Instruction.ADD));
		functionalUnits.add(new FunctionalUnit(Instruction.MULT));
		functionalUnits.add(new FunctionalUnit(Instruction.MULT));
		functionalUnits.add(new FunctionalUnit(Instruction.DIV));

		Instruction instruction;

		instruction = new Instruction(0, Instruction.LOAD_WORD, getRegister(6),
				getRegister(1), getRegister(6), 32, 0);

		Memory.storeInstructionUsingPC(0, instruction);

		instruction = new Instruction(1, Instruction.LOAD_WORD, getRegister(2),
				getRegister(1), null, 33, 0);

		Memory.storeInstructionUsingPC(1, instruction);

		instruction = new Instruction(2, Instruction.MULT, getRegister(0),
				getRegister(2), getRegister(4), 0, 10);
		Memory.storeInstructionUsingPC(2, instruction);

		instruction = new Instruction(3, Instruction.ADD, getRegister(7),
				getRegister(6), getRegister(2), 0, 2);
		Memory.storeInstructionUsingPC(3, instruction);

		instruction = new Instruction(4, Instruction.DIV, getRegister(3),
				getRegister(0), getRegister(6), 0, 20);
		Memory.storeInstructionUsingPC(4, instruction);

		instruction = new Instruction(5, Instruction.MULT, getRegister(6),
				getRegister(7), getRegister(2), 0, 10);
		Memory.storeInstructionUsingPC(5, instruction);

		instruction = new Instruction(6, Instruction.MULT, getRegister(4),
				getRegister(0), getRegister(2), 0, 10);
		Memory.storeInstructionUsingPC(6, instruction);

		instruction = new Instruction(7, Instruction.MULT, getRegister(6),
				getRegister(4), getRegister(3), 0, 10);
		Memory.storeInstructionUsingPC(7, instruction);

		instruction = new Instruction(8, Instruction.ADD, getRegister(3),
				getRegister(2), getRegister(5), 0, 2);
		Memory.storeInstructionUsingPC(8, instruction);

		instruction = new Instruction(9, Instruction.NAND, getRegister(4),
				getRegister(1), getRegister(7), 0, 2);
		Memory.storeInstructionUsingPC(9, instruction);

		// Caches
		nc = new L1Cache(L1Cache.WRITE_BACK, 10, 256, 64, 2);
		nc2 = new L2Cache(L1Cache.WRITE_BACK, 10, 256, 64, 2);
		nc3 = new L3Cache(L1Cache.WRITE_BACK, 10, 512, 64, 2);
		Fetch.l3Cache = nc3;
		Fetch.l2Cache = nc2;
		Fetch.l1Cache = nc;

		nc3.setL1(nc);
		nc3.setL2(nc2);
		nc2.setL3(nc3);
		nc2.setL1(nc);
		nc.setL2(nc2);
		nc.setL3(nc3);

		new Cache(3, nc, nc2, nc3);
	}

	public static void program1() throws Exception {
		// R4 <-- R0*R2
		// R6 <-- R4*R3
		// R3 <-- R2+R5
		// R4 <-- R1+R7
		m = 2;
		Memory.programSize = 4;
		mem = new Memory(1024, 100);
		Memory.store(0, 4);
		Memory.store(1, 6);
		Memory.store(2, 8);
		Memory.store(3, 9);
		Memory.store(4, 110);
		Memory.store(5, 3);
		Memory.store(6, 7);
		Memory.store(7, 6);
		Memory.store(32, 100);
		Memory.store(33, 8);
		Memory.store(34, 2);
		Memory.store(34, 9);
		
		reg0.setValue(5);
		reg1.setValue(3);
		reg2.setValue(4);
		reg3.setValue(2);
		reg4.setValue(7);
		reg5.setValue(2);
		reg6.setValue(10);
		reg7.setValue(1);

		reservationStations.add(new ReservationStation());
		reservationStations.add(new ReservationStation());
		reservationStations.add(new ReservationStation());

		functionalUnits.add(new FunctionalUnit(Instruction.ADD));
		functionalUnits.add(new FunctionalUnit(Instruction.ADD));
		functionalUnits.add(new FunctionalUnit(Instruction.MULT));
		functionalUnits.add(new FunctionalUnit(Instruction.MULT));

		Instruction instruction;
		instruction = new Instruction(0, Instruction.MULT, getRegister(4),
				getRegister(0), getRegister(2), 0, 10);
		Memory.storeInstructionUsingPC(0, instruction);

		instruction = new Instruction(1, Instruction.MULT, getRegister(6),
				getRegister(4), getRegister(3), 0, 10);
		Memory.storeInstructionUsingPC(1, instruction);

		instruction = new Instruction(2, Instruction.ADD, getRegister(3),
				getRegister(2), getRegister(5), 0, 2);
		Memory.storeInstructionUsingPC(2, instruction);

		instruction = new Instruction(3, Instruction.ADD, getRegister(4),
				getRegister(1), getRegister(7), 0, 2);
		Memory.storeInstructionUsingPC(3, instruction);

		// Caches
		nc = new L1Cache(L1Cache.WRITE_BACK, 10, 256, 64, 2);
		nc2 = new L2Cache(L1Cache.WRITE_BACK, 10, 256, 64, 2);
		nc3 = new L3Cache(L1Cache.WRITE_BACK, 10, 512, 64, 2);
		Fetch.l3Cache = nc3;
		Fetch.l2Cache = nc2;
		Fetch.l1Cache = nc;

		nc3.setL1(nc);
		nc3.setL2(nc2);
		nc2.setL3(nc3);
		nc2.setL1(nc);
		nc.setL2(nc2);
		nc.setL3(nc3);

		new Cache(3, nc, nc2, nc3);
	}
	
	public static void program4() throws Exception {
		m = 4;
		reg0.setValue(0);
		reg1.setValue(3);
		reg2.setValue(4);
		reg3.setValue(2);
		reg4.setValue(-7);
		reg5.setValue(2);
		reg6.setValue(10);
		reg7.setValue(5+1018);
		
		Memory.programSize = 5;
		mem = new Memory(1024, 100);
		Memory.store(0, 4);
		Memory.store(1, 6);
		Memory.store(2, 8);
		Memory.store(3, 9);
		Memory.store(4, 1000);
		Memory.store(5, 3);
		Memory.store(6, 7);
		Memory.store(7, 6);
		Memory.store(32, 100);
		Memory.store(33, 8);
		Memory.store(34, 2);
		Memory.store(34, 9);

		reservationStations.add(new ReservationStation());
		reservationStations.add(new ReservationStation());
		reservationStations.add(new ReservationStation());
		reservationStations.add(new ReservationStation());

		functionalUnits.add(new FunctionalUnit(Instruction.ADD));
		functionalUnits.add(new FunctionalUnit(Instruction.ADD));
		functionalUnits.add(new FunctionalUnit(Instruction.MULT));
		functionalUnits.add(new FunctionalUnit(Instruction.MULT));

		//SW R4, R0, 4
		Instruction instruction;
		instruction = new Instruction(0, Instruction.STORE_WORD, getRegister(4),
				getRegister(0), getRegister(2), 4, 10);
		Memory.storeInstructionUsingPC(0, instruction);

		//NAND R6, R1, R4
		instruction = new Instruction(1, Instruction.NAND, getRegister(6),
				getRegister(1), getRegister(4), 0, 10);
		Memory.storeInstructionUsingPC(1, instruction);

		//JALR R3, R7
		instruction = new Instruction(2, Instruction.JUMP_AND_LINK, getRegister(3),
				getRegister(7), getRegister(5), 0, 2);
		Memory.storeInstructionUsingPC(2, instruction);
		
		//JALR R3, R7
				instruction = new Instruction(3, Instruction.JUMP, getRegister(0),
						getRegister(7), getRegister(5), 1, 2);
				Memory.storeInstructionUsingPC(3, instruction);
		
		//RET R4
		instruction = new Instruction(4, Instruction.RETURN, getRegister(3),
						getRegister(1), getRegister(7), 0, 2);
				Memory.storeInstructionUsingPC(4, instruction);
		
	
		

		// Caches
		nc = new L1Cache(L1Cache.WRITE_BACK, 10, 256, 64, 4);
		nc2 = new L2Cache(L1Cache.WRITE_BACK, 10, 256, 64, 4);
		nc3 = new L3Cache(L1Cache.WRITE_BACK, 10, 512, 64, 4);
		Fetch.l3Cache = nc3;
		Fetch.l2Cache = nc2;
		Fetch.l1Cache = nc;

		nc3.setL1(nc);
		nc3.setL2(nc2);
		nc2.setL3(nc3);
		nc2.setL1(nc);
		nc.setL2(nc2);
		nc.setL3(nc3);

		new Cache(3, nc, nc2, nc3);
	}
	
	public static String getProgram1Inst() {
		return "MUL R0, R4, R2.\nMUL R6, R4, R3.\nADD R3, R2, R5.\nADD R4,R1,R7\n";  
	}
	
	public static String getProgram2Inst() {
		return "LW R6, R1, #32.\nLW R2, R1, #33.\nMUL R0, R2, R4.\n" +
				"ADD R7, R6, R2.\nDIV R3, R0, R6.\nMUL R6, R7, R2.\n" +
				"MUL R4, R0, R2.\nMUL R6, R4, R3.\nADD R3, R2, R5.\nADD R4, R1, R7.\n";  
	}
	
	public static String getProgram3Inst() {
		return "MUL R0, R2, R4.\nADDI R2, R2.\nBEQ R2, R3, #1.\nJMP R4, #-4.\n";  
	}

	public static void program3() throws Exception {
		m = 4;
		reg0.setValue(5);
		reg1.setValue(1);
		reg2.setValue(1);
		reg3.setValue(10);
		reg4.setValue(0);
		reservationStations.add(new ReservationStation());
		reservationStations.add(new ReservationStation());
		reservationStations.add(new ReservationStation());
		reservationStations.add(new ReservationStation());

		functionalUnits.add(new FunctionalUnit(Instruction.ADD));
		functionalUnits.add(new FunctionalUnit(Instruction.MULT));

		Memory.programSize = 4;
		mem = new Memory(1024, 100);
		Memory.store(0, 4);
		Memory.store(1, 6);
		Memory.store(2, 8);
		Memory.store(3, 9);
		Memory.store(4, 110);
		Memory.store(5, 3);
		Memory.store(6, 7);
		Memory.store(7, 6);
		Memory.store(32, 100);
		Memory.store(33, 8);
		Memory.store(34, 2);
		Memory.store(34, 9);
		
		Instruction instruction;
		instruction = new Instruction(0, Instruction.MULT, getRegister(1),
				getRegister(1), getRegister(2), 0, 10);
		Memory.storeInstructionUsingPC(0, instruction);

		instruction = new Instruction(1, Instruction.ADDI, getRegister(2),
				getRegister(2), null, 1, 2);
		Memory.storeInstructionUsingPC(1, instruction);

		instruction = new Instruction(2, Instruction.BRANCH_IF_EQUAL,
				getRegister(2), getRegister(3), getRegister(5), 1, 2);
		Memory.storeInstructionUsingPC(2, instruction);

		instruction = new Instruction(3, Instruction.JUMP, getRegister(4),
				getRegister(3), getRegister(5), -4, 2);
		Memory.storeInstructionUsingPC(3, instruction);

		L1Cache nc = new L1Cache(L1Cache.WRITE_BACK, 10, 256, 64, 2);
		L2Cache nc2 = new L2Cache(L1Cache.WRITE_BACK, 10, 256, 64, 2);
		L3Cache nc3 = new L3Cache(L1Cache.WRITE_BACK, 10, 512, 64, 2);
		Fetch.l3Cache = nc3;
		Fetch.l2Cache = nc2;
		Fetch.l1Cache = nc;

		nc3.setL1(nc);
		nc3.setL2(nc2);
		nc2.setL3(nc3);
		nc2.setL1(nc);
		nc.setL2(nc2);
		nc.setL3(nc3);

		new Cache(3, nc, nc2, nc3);
	}

	/**
	 * Grouped registers getter
	 * 
	 * @param i
	 *            index of the register wanted
	 * @return the register with the given index
	 * @throws Exception
	 */
	public static Register getRegister(int i) throws Exception {
		switch (i) {
		case 0:
			return reg0;
		case 1:
			return reg1;
		case 2:
			return reg2;
		case 3:
			return reg3;
		case 4:
			return reg4;
		case 5:
			return reg5;
		case 6:
			return reg6;
		case 7:
			return reg7;
		default:
			throw new Exception(UNDEFINED_REGISTER);
		}
	}

	/**
	 * removes instructions from reservation station after certain id.
	 * 
	 * @param id
	 *            id that i want all reservation stations with id after it.
	 */
	public static void removeFromReservationAfterId(int id) {
		for (int i = 0; i < reservationStations.size(); i++) {
			if (reservationStations.get(i).getIns() != null) {
				if (reservationStations.get(i).getIns().getID() > id) {
					reservationStations.get(i).setFull(false);
					reservationStations.get(i).setReserve(false);
					reservationStations.get(i).setIns(null);
				}
			}
		}
	}

	/**
	 * removes instructions from rob after certain id.
	 * 
	 * @param id
	 *            id that i want all reservation stations with id after it.
	 */
	public static void removeFromRobAfterId(int id) {
		LinkedList<ROBEntry> robe = new LinkedList<ROBEntry>();
		Instruction ins1 = Commit.instructions.get(Commit.getInstById(id));
		for (int i = 0; i < rob.size(); i++) {
			int index = Commit.getInstById(rob.get(i).getID());
			if(index!=-1){
			Instruction ins2 = Commit.instructions.get(index);
			if(ins2.getDecStartTime()>=ins1.getDecStartTime()){
			if (rob.get(i).getID() > id) {
				robe.add(rob.get(i));
			}
			}
		}else{
			if (rob.get(i).getID() > id) {
				robe.add(rob.get(i));
			}
		}
		}
		rob.removeAll(robe);
	}

	public static void main(String[] args) throws Exception {

		program2();

		System.out.println("3ali 3ali 3ali: " + Memory.mem.length);
		/*
		 * Instruction instruction1 = new Instruction(0 ,Instruction.ADD, reg6,
		 * reg2, reg3, 0, 2); Memory.storeInstructionUsingPC(0, instruction1);
		 * Instruction instruction2 = new Instruction(1,Instruction.ADD, reg4,
		 * reg5, reg3, 0, 2);
		 * 
		 * Memory.storeInstructionUsingPC(1, instruction2); Instruction
		 * instruction3 = new Instruction(7,Instruction.RETURN, reg7, reg5,
		 * reg2, 0, 2); Memory.storeInstructionUsingPC(7,instruction3);
		 * Memory.storeInstructionUsingPC(3, new Instruction(3,Instruction.ADD,
		 * reg4, reg5, reg3, 0, 2)); Memory.storeInstructionUsingPC(2, new
		 * Instruction(2,Instruction.JUMP_AND_LINK, reg7, reg5, reg3, 0, 2));
		 * Memory.storeInstructionUsingPC(5, new Instruction(5,Instruction.ADD,
		 * reg4, reg5, reg3, 0, 2)); Memory.storeInstructionUsingPC(6, new
		 * Instruction(6,Instruction.ADD, reg4, reg5, reg3, 0, 2));
		 * Memory.storeInstructionUsingPC(4,new Instruction(4,Instruction.ADD,
		 * reg2, reg5, reg3, 0, 2));
		 * 
		 * createInstruction(); reservationStations.add(new
		 * ReservationStation()); reservationStations.add(new
		 * ReservationStation()); reservationStations.add(new
		 * ReservationStation()); reservationStations.add(new
		 * ReservationStation()); reservationStations.add(new
		 * ReservationStation()); reservationStations.add(new
		 * ReservationStation());
		 * 
		 * //reservationStations.add(new ReservationStation());
		 * functionalUnits.add(new FunctionalUnit(Instruction.ADD));
		 * //functionalUnits.add(new FunctionalUnit(list.get(1).getType()));
		 * functionalUnits.add(new FunctionalUnit(Instruction.ADD));
		 * functionalUnits.add(new FunctionalUnit(Instruction.ADD));
		 * functionalUnits.add(new FunctionalUnit(Instruction.ADD));
		 * //functionalUnits.add(new FunctionalUnit(Instruction.JUMP_AND_LINK));
		 * //functionalUnits.add(new FunctionalUnit(Instruction.RETURN));
		 * //functionalUnits.add(new FunctionalUnit(Instruction.JUMP));
		 * //functionalUnits.add(new FunctionalUnit(list.get(3).getType()));
		 */

		/*
		 * while (currentTime < 10000) {
		 * 
		 * Commit.commit(rob, currentTime); Execute.execute(currentTime);
		 * Issue.issue(currentTime); Dispatch.dispatch(currentTime);
		 * Decode.decode(currentTime); Fetch.fetch(currentTime); currentTime++;
		 * }
		 */

		simulate(1550);				
		//simulate(50);
		//simulate(50);
		System.out.println(reg1.value);
		System.out.println(reg3.value);
		System.out.println(L1Cache.hit);
		System.out.println(L1Cache.hitI/(double)L1Cache.accessTimesI);
		System.out.println(L1Cache.missI/(double)L1Cache.accessTimesI);

		System.out.println(L2Cache.hit/(double)L2Cache.accessTimes);

		System.out.println(L2Cache.miss/(double)L2Cache.accessTimes);

		System.out.println(L3Cache.hit/(double)L3Cache.accessTimes);

		System.out.println(L3Cache.miss/(double)L3Cache.accessTimes);
		

	}

	public static void simulate(int cycles) throws Exception {
		while (true) {
			Commit.commit(rob, currentTime);
			Execute.execute(currentTime);
			Issue.issue(currentTime);
			Dispatch.dispatch(currentTime);
			Decode.decode(currentTime);
			Fetch.fetch(currentTime);
			currentTime++;
			if(currentTime == 298){
				System.out.println("wezaaaaa" + reg4.value);
				System.out.println("wezaaaaa" + reg0.value);

			}
			if (currentTime % cycles == 0) {
				break;
			}
		}
		
		System.out.println("---------------Fetch---------------");
		System.out.println(Fetch.instructions.toString());
		System.out.println("---------------Fetch---------------");
		System.out.println(Decode.instructions.toString());
		System.out.println("---------------Fetch---------------");
		System.out.println(Issue.instructions.toString());
		System.out.println("---------------Fetch---------------");
		System.out.println(Dispatch.instructions.toString());
		System.out.println("---------------Fetch---------------");
		System.out.println(Execute.ins.toString());
		System.out.println("*************ROB*************");
		System.out.println(rob.toString());		
		System.out.println("*************L1 Cache*************");
		System.out.println(Cache.l1Cache.toString());		
		if (Cache.l2Cache != null) {
			System.out.println("***************L2 Cache**************");
			System.out.println(Cache.l2Cache.toString());
		}
		if (Cache.l3Cache != null) {
			System.out.println("*********L3 Cache********************");
			System.out.println(Cache.l3Cache.toString());
		}		
		System.out.println("*********Memory********************");
		System.out.println(mem.toString());

		for (int j = 0; j < Commit.instructions.size(); j++) {
			System.out.println(Commit.instructions.get(j).toString());
		}
		System.out.println(functionalUnits);
		System.out.println(L1Cache.hitI/(double)L1Cache.accessTimesI);
		System.out.println(L1Cache.missI/(double)L1Cache.accessTimesI);

		System.out.println(L2Cache.hit/(double)L2Cache.accessTimes);

		System.out.println(L2Cache.miss/(double)L2Cache.accessTimes);

		System.out.println(L3Cache.hit/(double)L3Cache.accessTimes);

		System.out.println(L3Cache.miss/(double)L3Cache.accessTimes);
	}

}
